package com.lizk.tools.hotdeploy2.core;

import java.io.File;
import java.util.Objects;

/**
 * 
 * <p>描述：对外公开的使用工具</p>
 * @author lizk
 *
 */
public class AutoExeClassUtil {
	
	//上下文的环境
	private AutoExeClassCentext classLoadUtil = null;
	
	//锁对象
	private static Object lockObject = new Object();
	
	
	//暂存的配置参数
	private static String path = null;				//需要扫描的目录
	private static String packageName = null;		//指定使用自定义类加载器加载的包名
	private static ClassLoader parentLoader = null;	//父级类加载器
	private static int init = 0;					//第一次执行定时扫描的延迟时间
	private static int delay = 5;					//每次执行间隔
	
	
	public static void config(String path,String packageName,ClassLoader parentLoader,int init ,int delay){
		//对lockObject加锁，防止多个线程同时操作config
		synchronized (lockObject) {
			if (AutoExeClassUtil.path != null) {
				System.err.println("重复配置参数!");
				return;
			}
			
			if (path == null || packageName == null || parentLoader == null || Objects.equals("", path)
					|| Objects.equals("", packageName)) {
				System.err.println("配置参数有误!");
				throw new AutoExeClassException("配置参数有误!");
			}
			
			File file = new File(path);
			
			if (!file.exists() || !file.isDirectory()) {
				System.err.println("扫描路径不存在或不是目录!");
				throw new AutoExeClassException("扫描路径不存在或不是目录!");
			}
			
			AutoExeClassUtil.path = path;
			AutoExeClassUtil.packageName = packageName;
			AutoExeClassUtil.parentLoader = parentLoader;
			AutoExeClassUtil.init = init;
			AutoExeClassUtil.delay = delay;
			
		}
	}

	public static void config(String path, String packageName, ClassLoader parentLoader) {
		config(path, packageName, parentLoader, AutoExeClassUtil.init, AutoExeClassUtil.delay);
	}
	
	
	/**
	 * 静态内部类实现单例模式
	 */
	public static AutoExeClassUtil getInstance(){
		return CreateInstance.getInstance();
	}
	
	/**
	 * 静态内部类，为了实现单利模式
	 * @author lizk
	 */
	public static class CreateInstance{
		private static AutoExeClassUtil autoExeClassUtil = new AutoExeClassUtil(path,packageName,parentLoader,init,delay); 
		public static AutoExeClassUtil getInstance(){
			return autoExeClassUtil;
		}
	}
	
	
	/**
	 * 构造方法
	 * @param path	要扫描的路径
	 * @param packageNmae	包名
	 * @param parentLoader	父级classloader
	 */
	private AutoExeClassUtil(String path, String packageNmae, ClassLoader parentLoader, int init, int delay) {
		if (path == null || packageNmae == null || parentLoader == null) {
			System.err.println("请使用config方法配置参数!");
			throw new AutoExeClassException("请使用config方法配置参数!");
		}
		this.classLoadUtil = new AutoExeClassCentext(path, packageNmae, parentLoader, init, delay);
	}
	
	
	
	/**
	 * 执行指定class的方法
	 * @param ClazzName		class名称
	 * @param methodName	方法名称
	 * @param parameters	参数类型
	 * @param objects		参数
	 * @return
	 */
	public Object exeClazz(String ClazzName ,String methodName ,Class<?>[] parameters,Object[] objects){
		Object result = null;
		try {
			result = classLoadUtil.getChildClassLoader().exeClazz(ClazzName, methodName, parameters, objects);
		} catch (Exception e) {
			System.err.println("动态执行代码失败");
			throw new AutoExeClassException("动态执行代码失败", e);
		}
		return result;
	}
	
	
	/**
	 * 启动文件扫描，如果文件有变动，重新加载class文件
	 */
	public void start(){
		try {
			classLoadUtil.getCheckFileTask().start();
		} catch (Exception e) {
			System.err.println("启动文件扫描失败");
			throw new AutoExeClassException("启动文件扫描失败",e);
		}
	}
	
}
